home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
lib
/
calc
/
zmath.h
< prev
Wrap
C/C++ Source or Header
|
1995-07-17
|
12KB
|
345 lines
/*
* Copyright (c) 1993 David I. Bell
* Permission is granted to use, distribute, or modify this source,
* provided that this copyright notice remains intact.
*
* Data structure declarations for extended precision integer arithmetic.
* The assumption made is that a long is 32 bits and shorts are 16 bits,
* and longs must be addressible on word boundaries.
*/
#ifndef ZMATH_H
#define ZMATH_H
#include <stdio.h>
#include "alloc.h"
#include "endian.h"
#include "have_stdlib.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifndef ALLOCTEST
# if defined(CALC_MALLOC)
# define freeh(p) (((void *)p == (void *)_zeroval_) || \
((void *)p == (void *)_oneval_) || free((void *)p))
# else
# define freeh(p) { if (((void *)p != (void *)_zeroval_) && \
((void *)p != (void *)_oneval_)) free((void *)p); }
# endif
#endif
typedef short FLAG; /* small value (e.g. comparison) */
typedef int BOOL; /* TRUE or FALSE value */
typedef unsigned long HASH; /* hash value */
#if !defined(TRUE)
#define TRUE ((BOOL) 1) /* booleans */
#endif
#if !defined(FALSE)
#define FALSE ((BOOL) 0)
#endif
/*
* NOTE: FULL must be twice the storage size of a HALF
* LEN storage size must be <= FULL storage size
*/
typedef unsigned short HALF; /* unit of number storage */
typedef unsigned long FULL; /* double unit of number storage */
typedef long LEN; /* unit of length storage */
#define BASE ((FULL) 65536) /* base for calculations (2^16) */
#define BASE1 ((FULL) (BASE - 1)) /* one less than base */
#define BASEB 16 /* number of bits in base */
#define BASEDIG 5 /* number of digits in base */
#define MAXHALF ((FULL) 0x7fff) /* largest positive half value */
#define MAXFULL ((FULL) 0x7fffffff) /* largest positive full value */
#define TOPHALF ((FULL) 0x8000) /* highest bit in half value */
#define TOPFULL ((FULL) 0x80000000) /* highest bit in full value */
#define MAXLEN ((LEN) 0x7fffffff) /* longest value allowed */
#define MAXREDC 5 /* number of entries in REDC cache */
#define SQ_ALG2 20 /* size for alternative squaring */
#define MUL_ALG2 20 /* size for alternative multiply */
#define POW_ALG2 40 /* size for using REDC for powers */
#define REDC_ALG2 50 /* size for using alternative REDC */
typedef union {
FULL ivalue;
struct {
HALF Svalue1;
HALF Svalue2;
} sis;
} SIUNION;
#if !defined(BYTE_ORDER)
#include <machine/endian.h>
#endif
#if !defined(LITTLE_ENDIAN)
#define LITTLE_ENDIAN 1234 /* Least Significant Byte first */
#endif
#if !defined(BIG_ENDIAN)
#define BIG_ENDIAN 4321 /* Most Significant Byte first */
#endif
/* PDP_ENDIAN - LSB in word, MSW in long is not supported */
#if BYTE_ORDER == LITTLE_ENDIAN
# define silow sis.Svalue1 /* low order half of full value */
# define sihigh sis.Svalue2 /* high order half of full value */
#else
# if BYTE_ORDER == BIG_ENDIAN
# define silow sis.Svalue2 /* low order half of full value */
# define sihigh sis.Svalue1 /* high order half of full value */
# else
:@</*/>@: BYTE_ORDER must be BIG_ENDIAN or LITTLE_ENDIAN :@</*/>@:
# endif
#endif
typedef struct {
HALF *v; /* pointer to array of values */
LEN len; /* number of values in array */
BOOL sign; /* sign, nonzero is negative */
} ZVALUE;
/*
* Function prototypes for integer math routines.
*/
#if defined(__STDC__)
#define MATH_PROTO(a) a
#else
#define MATH_PROTO(a) ()
#endif
extern HALF * alloc MATH_PROTO((LEN len));
#ifdef ALLOCTEST
extern void freeh MATH_PROTO((HALF *));
#endif
/*
* Input, output, and conversion routines.
*/
extern void zcopy MATH_PROTO((ZVALUE z, ZVALUE *res));
extern void itoz MATH_PROTO((long i, ZVALUE *res));
extern void atoz MATH_PROTO((char *s, ZVALUE *res));
extern long ztoi MATH_PROTO((ZVALUE z));
extern void zprintval MATH_PROTO((ZVALUE z, long decimals, long width));
extern void zprintx MATH_PROTO((ZVALUE z, long width));
extern void zprintb MATH_PROTO((ZVALUE z, long width));
extern void zprinto MATH_PROTO((ZVALUE z, long width));
/*
* Basic numeric routines.
*/
extern void zmuli MATH_PROTO((ZVALUE z, long n, ZVALUE *res));
extern long zdivi MATH_PROTO((ZVALUE z, long n, ZVALUE *res));
extern long zmodi MATH_PROTO((ZVALUE z, long n));
extern void zadd MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zsub MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zmul MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zdiv MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res, ZVALUE *rem));
extern void zquo MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *rem));
extern BOOL zdivides MATH_PROTO((ZVALUE z1, ZVALUE z2));
extern void zor MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zand MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zxor MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zshift MATH_PROTO((ZVALUE z, long n, ZVALUE *res));
extern void zsquare MATH_PROTO((ZVALUE z, ZVALUE *res));
extern long zlowbit MATH_PROTO((ZVALUE z));
extern long zhighbit MATH_PROTO((ZVALUE z));
extern void zbitvalue MATH_PROTO((long n, ZVALUE *res));
extern BOOL zisset MATH_PROTO((ZVALUE z, long n));
extern BOOL zisonebit MATH_PROTO((ZVALUE z));
extern BOOL zisallbits MATH_PROTO((ZVALUE z));
extern FLAG ztest MATH_PROTO((ZVALUE z));
extern FLAG zrel MATH_PROTO((ZVALUE z1, ZVALUE z2));
extern BOOL zcmp MATH_PROTO((ZVALUE z1, ZVALUE z2));
/*
* More complicated numeric functions.
*/
extern long iigcd MATH_PROTO((long i1, long i2));
extern void zgcd MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zlcm MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zreduce MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *z1res, ZVALUE *z2res));
extern void zfact MATH_PROTO((ZVALUE z, ZVALUE *dest));
extern void zpfact MATH_PROTO((ZVALUE z, ZVALUE *dest));
extern void zlcmfact MATH_PROTO((ZVALUE z, ZVALUE *dest));
extern void zperm MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zcomb MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern BOOL zprimetest MATH_PROTO((ZVALUE z, long count));
extern FLAG zjacobi MATH_PROTO((ZVALUE z1, ZVALUE z2));
extern void zfib MATH_PROTO((ZVALUE z, ZVALUE *res));
extern void zpowi MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void ztenpow MATH_PROTO((long power, ZVALUE *res));
extern void zpowermod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3, ZVALUE *res));
extern BOOL zmodinv MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern BOOL zrelprime MATH_PROTO((ZVALUE z1, ZVALUE z2));
extern long zlog MATH_PROTO((ZVALUE z1, ZVALUE z2));
extern long zlog10 MATH_PROTO((ZVALUE z));
extern long zdivcount MATH_PROTO((ZVALUE z1, ZVALUE z2));
extern long zfacrem MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *rem));
extern void zgcdrem MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern long zlowfactor MATH_PROTO((ZVALUE z, long count));
extern long zdigits MATH_PROTO((ZVALUE z1));
extern FLAG zdigit MATH_PROTO((ZVALUE z1, long n));
extern BOOL zsqrt MATH_PROTO((ZVALUE z1, ZVALUE *dest));
extern void zroot MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *dest));
extern BOOL zissquare MATH_PROTO((ZVALUE z));
extern HASH zhash MATH_PROTO((ZVALUE z));
#if 0
extern void zapprox MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res1, ZVALUE *res2));
#endif
#if 0
extern void zmulmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3, ZVALUE *res));
extern void zsquaremod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zsubmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3, ZVALUE *res));
#endif
extern void zminmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern BOOL zcmpmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3));
/*
* These functions are for internal use only.
*/
extern void ztrim MATH_PROTO((ZVALUE *z));
extern void zshiftr MATH_PROTO((ZVALUE z, long n));
extern void zshiftl MATH_PROTO((ZVALUE z, long n));
extern HALF *zalloctemp MATH_PROTO((LEN len));
extern void initmasks MATH_PROTO((void));
/*
* Modulo arithmetic definitions.
* Structure holding state of REDC initialization.
* Multiple instances of this structure can be used allowing
* calculations with more than one modulus at the same time.
* Len of zero means the structure is not initialized.
*/
typedef struct {
LEN len; /* number of words in binary modulus */
ZVALUE mod; /* modulus REDC is computing with */
ZVALUE inv; /* inverse of modulus in binary modulus */
ZVALUE one; /* REDC format for the number 1 */
} REDC;
extern REDC *zredcalloc MATH_PROTO((ZVALUE z1));
extern void zredcfree MATH_PROTO((REDC *rp));
extern void zredcencode MATH_PROTO((REDC *rp, ZVALUE z1, ZVALUE *res));
extern void zredcdecode MATH_PROTO((REDC *rp, ZVALUE z1, ZVALUE *res));
extern void zredcmul MATH_PROTO((REDC *rp, ZVALUE z1, ZVALUE z2, ZVALUE *res));
extern void zredcsquare MATH_PROTO((REDC *rp, ZVALUE z1, ZVALUE *res));
extern void zredcpower MATH_PROTO((REDC *rp, ZVALUE z1, ZVALUE z2, ZVALUE *res));
/*
* macro expansions to speed this thing up
*/
#define ziseven(z) (!(*(z).v & 01))
#define zisodd(z) (*(z).v & 01)
#define ziszero(z) ((*(z).v == 0) && ((z).len == 1))
#define zisneg(z) ((z).sign)
#define zispos(z) (((z).sign == 0) && (*(z).v || ((z).len > 1)))
#define zisunit(z) ((*(z).v == 1) && ((z).len == 1))
#define zisone(z) ((*(z).v == 1) && ((z).len == 1) && !(z).sign)
#define zisnegone(z) ((*(z).v == 1) && ((z).len == 1) && (z).sign)
#define zistwo(z) ((*(z).v == 2) && ((z).len == 1) && !(z).sign)
#define zisleone(z) ((*(z).v <= 1) && ((z).len == 1))
#define zistiny(z) ((z).len == 1)
#define zissmall(z) (((z).len < 2) || (((z).len == 2) && (((short)(z).v[1]) >= 0)))
#define zisbig(z) (((z).len > 2) || (((z).len == 2) && (((short)(z).v[1]) < 0)))
#define z1tol(z) ((long)((z).v[0]))
#define z2tol(z) (((long)((z).v[0])) + \
(((long)((z).v[1] & MAXHALF)) << BASEB))
#define zclearval(z) memset((z).v, 0, (z).len * sizeof(HALF))
#define zcopyval(z1,z2) memcpy((z2).v, (z1).v, (z1).len * sizeof(HALF))
#define zquicktrim(z) {if (((z).len > 1) && ((z).v[(z).len-1] == 0)) \
(z).len--;}
#define zfree(z) freeh((z).v)
/*
* Output modes for numeric displays.
*/
#define MODE_DEFAULT 0
#define MODE_FRAC 1
#define MODE_INT 2
#define MODE_REAL 3
#define MODE_EXP 4
#define MODE_HEX 5
#define MODE_OCTAL 6
#define MODE_BINARY 7
#define MODE_MAX 7
#define MODE_INITIAL MODE_REAL
/*
* Output routines for either FILE handles or strings.
*/
extern void math_chr MATH_PROTO((int ch));
extern void math_str MATH_PROTO((char *str));
extern void math_fill MATH_PROTO((char *str, long width));
extern void math_flush MATH_PROTO((void));
extern void math_divertio MATH_PROTO((void));
extern void math_cleardiversions MATH_PROTO((void));
extern void math_setfp MATH_PROTO((FILE *fp));
extern char *math_getdivertedio MATH_PROTO((void));
extern int math_setmode MATH_PROTO((int mode));
extern long math_setdigits MATH_PROTO((long digits));
#ifdef VARARGS
extern void math_fmt();
#else
extern void math_fmt MATH_PROTO((char *, ...));
#endif
/*
* The error routine.
*/
#ifdef VARARGS
extern void math_error();
#else
extern void math_error MATH_PROTO((char *, ...));
#endif
/*
* constants used often by the arithmetic routines
*/
extern HALF _zeroval_[], _oneval_[], _twoval_[], _tenval_[];
extern ZVALUE _zero_, _one_, _ten_;
extern BOOL _math_abort_; /* nonzero to abort calculations */
extern ZVALUE _tenpowers_[32]; /* table of 10^2^n */
extern int _outmode_; /* current output mode */
extern LEN _mul2_; /* size of number to use multiply algorithm 2 */
extern LEN _sq2_; /* size of number to use square algorithm 2 */
extern LEN _pow2_; /* size of modulus to use REDC for powers */
extern LEN _redc2_; /* size of modulus to use REDC algorithm 2 */
extern HALF *bitmask; /* bit rotation, norm 0 */
#endif
/* END CODE */